﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;

namespace Gaea.CodeFirst
{
    public static class GaeaCodeFirstExtension
    {
        /// <summary>
        /// 根据找到的继承了GaeaBasicPower的Model进行相关数据库操作
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="gaeaBasicPower"></param>
        public async static void ExecuteSql<T>(this GaeaBasicPower gaeaBasicPower) where T : class
        {
            var types = Assembly.GetCallingAssembly().GetTypes();
            var TypeOfGaeaBasicPower = typeof(GaeaBasicPower<>);

            foreach (var type in types)
            {
                var baseType = type.GetGenericTypeDefinition();

                baseType.GetProperties();//获取类所有字段属性

                while (baseType != null)
                {
                    if (baseType.Name == TypeOfGaeaBasicPower.Name)
                    {
                        var a = Attribute.GetCustomAttributes(type);


                        //根据继承GaeaSon的类名去数据库内搜索是否存在，不存在的话CreateNewTable，存在的话AlterTable
                        var className = type.Name;
                        await ExecuteTable<T>(gaeaBasicPower, className, TypeOfGaeaBasicPower);
                    }
                }
            }
        }
        public static async Task ExecuteTable<T>(this GaeaBasicPower gaeaBasicPower, string tableName, Type TypeOfGaeaBasicPower) where T : class
        {
            //查询数据库里所有表
            var allTables = await gaeaBasicPower.FindAsync<string>("show tables", new { });
            var enumerator = allTables.GetEnumerator();

            int i = 0;
            while (enumerator.MoveNext())
            {
                string DBTableName = enumerator.Current;
                if (DBTableName == tableName) //名字相同，表存在，修改表
                {
                    await AlterTable<T>(gaeaBasicPower, TypeOfGaeaBasicPower);
                    i = 0;
                    break;
                }
                i++;
            }
            if (i != 0) //即数据库里没有那个表，新建表
            {
                await CreateNewTable<T>(gaeaBasicPower, TypeOfGaeaBasicPower);
            }

        }
        /// <summary>
        /// 新建表
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="gaeaBasicPower"></param>
        /// <param name="TypeOfGaeaBasicPower"></param>
        /// <returns></returns>
        public static async Task CreateNewTable<T>(this GaeaBasicPower gaeaBasicPower, Type TypeOfGaeaBasicPower) where T : class
        {
            //typeOfGaeaSon = typeof(T);
            PropertyInfo[] propertyInfo = typeof(T).GetProperties();
            string ColumnSql = "";
            foreach (var item in propertyInfo)
            {
                var column_name = item.Name;
                var column_type = item.PropertyType.Name;
                if (column_type == "String")
                {
                    column_type = "varchar(50)";
                }
                else if (column_type == "Int32")
                {
                    column_type = "int";
                }
                ColumnSql += column_name + column_type + ",";
            }
            ColumnSql = ColumnSql.Substring(0, ColumnSql.Length - 1);
            var sql = "CREATE TABLE " + gaeaBasicPower.CallGaeaName(gaeaBasicPower, TypeOfGaeaBasicPower) + " ( id int not null primary key auto_increment," + ColumnSql + ");";
            await gaeaBasicPower.ExecuteAsync(sql, null);
        }
        /// <summary>
        /// 修改表
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="gaeaBasicPower"></param>
        /// <param name="TypeOfGaeaBasicPower"></param>
        /// <returns></returns>
        public static async Task AlterTable<T>(this GaeaBasicPower gaeaBasicPower, Type TypeOfGaeaBasicPower) where T : class
        {
            PropertyInfo[] propertyInfo = typeof(T).GetProperties();
            string ColumnSql = "";
            Dictionary<string, string> keyValuePairs = new Dictionary<string, string>();
            var allColumns = await gaeaBasicPower.FindAsync<COLUMNS>("show columns from tablename=@tablename", new { tablename = gaeaBasicPower.CallGaeaName(gaeaBasicPower, TypeOfGaeaBasicPower) });
            var enumerator = allColumns.GetEnumerator();
            while (enumerator.MoveNext())
            {
                string ColumnName = enumerator.Current.Field;
                string ColumnType = enumerator.Current.Type;
                keyValuePairs.Add(ColumnName, ColumnType);    //将数据库表所有字段名及类型存入字典
            }

            foreach (var item in propertyInfo)
            {
                var column_name = item.Name;
                var column_type = item.PropertyType.Name;
                if (column_type == "String")
                {
                    column_type = "varchar(50)";
                }
                else if (column_type == "Int32")
                {
                    column_type = "int";
                }

                //与字典内数据对比，将没有的字段在数据表内新增
                if (keyValuePairs.ContainsKey(column_name) == false)
                {
                    ColumnSql = column_name + column_type;
                    var sql = "Alter TABLE " + gaeaBasicPower.CallGaeaName(gaeaBasicPower, TypeOfGaeaBasicPower) + " Add " + ColumnSql + " ;";
                    await gaeaBasicPower.ExecuteAsync(sql, null);
                }
                //包含该字段名，但类型不同的报错
                else if (keyValuePairs.ContainsKey(column_name) == true && keyValuePairs[column_name] != column_type)
                {
                    throw new Exception("This field already exists,and type is different!");
                }

            }
        }

        [AttributeUsage(AttributeTargets.Property)]
        public class GaeaSonStringLengthAttribute : Attribute
        {
            public string length { get; set; }
        }
    }
}
